"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.toRaw = exports.$delete = exports.$set = exports.reactive2 = exports.reactive = exports.isReactive = void 0;
var utils_1 = require("../utils");
var effect_1 = require("./effect");
var ref_1 = require("./ref");
/**
 * 代理对象是Arr时，为includes、indexOf、lastIndexOf添加track监听
 */
var arrayInstrumentations = {};
['includes', 'indexOf', 'lastIndexOf'].forEach(function (key) {
    arrayInstrumentations[key] = function () {
        var args = [];
        for (var _i = 0; _i < arguments.length; _i++) {
            args[_i] = arguments[_i];
        }
        // this：observed（代理后的对象）
        // 返回observed.__v_raw（被代理的对象target）
        var arr = toRaw(this);
        for (var i = 0, l = this.length; i < l; i++) {
            effect_1.track(arr, i + '');
        }
        // 方法执行获得的值
        var res = arr[key].apply(arr, args);
        if (res === -1 || res === false) {
            // 判断是否有代理对象
            return arr[key].apply(arr, args.map(toRaw));
        }
        else {
            return res;
        }
    };
});
exports.isReactive = function (v) {
    return v ? v.__v_isReactive === true : false;
};
var isObservableType = [Object, Array, Map, Set, WeakMap, WeakSet];
var canObserve = function (value) {
    return isObservableType.some(function (type) { return value instanceof type; });
};
function reactive(target) {
    if (!utils_1.isObject(target)) { // 如果不是对象，返回错误（不能代理）
        console.warn("value cannot be made reactive: " + String(target));
        return target;
    }
    // 如果已经被代理，则直接返回
    if (target.__v_raw)
        return target;
    if (target.__v_reactive)
        return target.__v_reactive;
    // 不可操作的target
    if (!canObserve(target))
        return target;
    var handler = reactiveHandler();
    var observed = new Proxy(target, handler);
    Object.defineProperty(target, '__v_reactive', {
        configurable: true,
        value: observed
    });
    return observed;
}
exports.reactive = reactive;
function reactive2(target) {
    if (!utils_1.isObject(target)) { // 如果不是对象，返回错误（不能代理）
        console.warn("value cannot be made reactive: " + String(target));
        return target;
    }
    // 如果已经被代理，则直接返回
    if (target.__v_raw)
        return target;
    if (target.__v_reactive)
        return target.__v_reactive;
    // 不可操作的target
    if (!canObserve(target))
        return target;
    var handler = Object.create(null);
    var depsMap = effect_1.createDepsMap(); // 依赖，存储在闭包中
    var observed = Object.create({
        __v_raw: target,
        __v_isReactive: true,
        __v_depsMap: depsMap
    });
    Object.keys(target).forEach(function (key) {
        var item = target[key];
        handler[key] = {
            configurable: true,
            enumerable: true,
            get: function () {
                effect_1.track(depsMap, key);
                var targetIsArray = utils_1.isArray(target); // 判断代理的是否是数组
                var res = target[key];
                return ref_1.isRef(res) ?
                    // 值是ref
                    targetIsArray ? res : res.value :
                    // 代理子对象
                    utils_1.isObject(res) ? reactive2(res) : res;
            },
            set: function (value) {
                target[key] = value;
                effect_1.trigger(depsMap, key, !item);
                return true;
            }
        };
    });
    Object.defineProperties(observed, handler);
    Object.defineProperty(target, '__v_reactive', {
        configurable: true,
        value: observed
    });
    return observed;
}
exports.reactive2 = reactive2;
function $set(observed, key, value) {
    var depsMap = observed.__v_depsMap;
    var target = observed.__v_raw;
    Object.defineProperty(observed, key, {
        configurable: true,
        enumerable: true,
        get: function () {
            effect_1.track(depsMap, key);
            var targetIsArray = utils_1.isArray(target); // 判断代理的是否是数组
            var res = target[key];
            return ref_1.isRef(res) ?
                // 值是ref
                targetIsArray ? res : res.value :
                // 代理子对象
                utils_1.isObject(res) ? reactive2(res) : res;
        },
        set: function (new_value) {
            target[key] = new_value;
            effect_1.trigger(depsMap, key, !!target[key]);
            return true;
        }
    });
    observed[key] = toRaw(value);
}
exports.$set = $set;
function $delete(observed, key) {
    var depsMap = observed.__v_depsMap;
    var target = observed.__v_raw;
    // 删除属性
    var result = Reflect.deleteProperty(target, key);
    if (result && !utils_1.hasOwn(target, key)) { // 删除成功后出发trigger
        // trigger(depsMap, key)
        effect_1.trigger(depsMap, effect_1.ITERATE_KEY);
    }
    return result;
}
exports.$delete = $delete;
/**
 * 生成Proxy的Handler
 * @return {ProxyHandler} ProxyHandler对象
 */
function reactiveHandler() {
    var depsMap = effect_1.createDepsMap(); // 依赖，存储在闭包中
    return {
        get: function (target, key, receiver) {
            if (key === '__v_raw')
                return target;
            if (key === '__v_isReactive')
                return true;
            var targetIsArray = utils_1.isArray(target); // 判断代理的是否是数组
            if (targetIsArray && utils_1.hasOwn(arrayInstrumentations, key)) {
                // 判断key值是否是'includes', 'indexOf', 'lastIndexOf' ,直接返回值（不做代理处理）
                return Reflect.get(arrayInstrumentations, key, receiver);
            }
            // res为获取值（res = target[key]）
            var res = Reflect.get(target, key, receiver);
            // 获取原型或Symbol直接返回值
            if (utils_1.isSymbol(key) || key === '__proto__')
                return res;
            effect_1.track(depsMap, key);
            return ref_1.isRef(res) ?
                // 值是ref
                targetIsArray ? res : res.value :
                // 代理子对象
                utils_1.isObject(res) ? reactive(res) : res;
        },
        set: function (target, key, value, receiver) {
            var oldValue = target[key];
            value = toRaw(value); // 获取被代理前的值（如果value是reactive的话）
            // oldValue为ref，修改值不是ref，则替换ref的value
            if (!utils_1.isArray(target) && ref_1.isRef(oldValue) && !ref_1.isRef(value)) {
                oldValue.value = value;
                return true;
            }
            var result = Reflect.set(target, key, value, receiver); // 设置值，返回是否成功
            effect_1.trigger(depsMap, key, !oldValue);
            return result;
        },
        deleteProperty: function (target, key) {
            // 删除属性
            var result = Reflect.deleteProperty(target, key);
            if (result && !utils_1.hasOwn(target, key)) { // 删除成功后出发trigger
                // trigger(depsMap, key)
                effect_1.trigger(depsMap, effect_1.ITERATE_KEY);
            }
            return result;
        },
        has: function (target, key) {
            var result = Reflect.has(target, key);
            effect_1.track(depsMap, key);
            return result;
        },
        ownKeys: function (target) {
            effect_1.track(depsMap, effect_1.ITERATE_KEY);
            return Reflect.ownKeys(target);
        }
    };
}
/**
 * 返回reactive的原对象（被代理前的对象）
 */
function toRaw(observed) {
    return (observed && toRaw(observed.__v_raw)) || observed;
}
exports.toRaw = toRaw;
